Skip to content

Conversation

cmanallen
Copy link
Member

@cmanallen cmanallen commented Oct 8, 2025

Normalize resolve-in-next-release release values between activity data and group resolution params. Also, fetches the latest semver release scoped to the packages present on the group.

Previously when resolving in the next semver release the release stored on the group resolution was the most recent time-ordered release. This PR changes that so we're setting the latest semver release as the release value.

But some projects can have multiple packages. Either old packages no longer in use or concurrent packages with their own ordering characteristics. By filtering by the package we force the group resolution to only consider releases relevant to the problem being solved.

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Oct 8, 2025
Copy link

codecov bot commented Oct 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff              @@
##           master   #101184       +/-   ##
============================================
+ Coverage   66.36%    81.10%   +14.73%     
============================================
  Files        8661      8673       +12     
  Lines      384271    384792      +521     
  Branches    24275     24275               
============================================
+ Hits       255020    312082    +57062     
+ Misses     128904     72363    -56541     
  Partials      347       347               

@cmanallen cmanallen marked this pull request as ready for review October 9, 2025 13:09
@cmanallen cmanallen requested a review from a team as a code owner October 9, 2025 13:09
cursor[bot]

This comment was marked as outdated.

"release": Release.objects.filter(
organization_id=release.organization_id,
version=current_release_version,
).get(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR looks good to me. One small question about the extra query we have here to get the release that matches current_release_version--can/should we remove the need for this? Disadvantages are a little bit of extra latency and edge cases where get() raises Release.DoesNotExist.

We could do an easy fix in the semver path by returning current_release alongside current_release_version in get_current_release_version_of_group, then doing current_release or Release.objects.filter( here.

The non-semver path also queries the release and returns only the version (ugh), but the logic is buried fairly deep and uses caching so I understand if we don't want to change anything in this path. But it would be cleaner and save us a query if we change get_current_release_version_of_group to get_current_release_of_group altogether. If we want to merge this PR as is, I'm happy to investigate more and potentially write a followup ref PR that does this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Its not ideal. Definitely something we could address in a follow-up. For this PR, we have enough to worry about so we'll limit the blast radius.

On performance, yes its another query but its indexed so it will be fast. These things do add up so its best to not add queries too cavalierly. My long term goal is to refactor this code path entirely. The code, as is, is incomprehensible. An intermediate step might be the change you suggested or it might be something deeper. It just depends on the performance we measure in production and if its causing issues or not. If its not causing issues then we might focus our efforts on more substantial improvements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Was gonna ask how I can follow up on measuring perf in prod but I think your DD walkthrough is coming up anyway!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sentry's tracing product would be better! You can filter to the PUT request and find this span in there. You can see how the system performs in aggregate and determine if you need to make a perf change or not.

"release": Release.objects.filter(
organization_id=release.organization_id,
version=current_release_version,
).get(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Unhandled Exception When Fetching Nonexistent Release

During issue resolution in semver projects, the code fetches a Release object using .get() with current_release_version. If current_release_version doesn't correspond to an existing Release in the database, this raises Release.DoesNotExist, causing an unhandled exception.

Fix in Cursor Fix in Web

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True but since the current_release_version has already been shown to exist in the db the only way this could happen is if the release was deleted (which we don't allow). Technically this could raise but I'm not sure what I'd do with the exception anyway. Raising seems to be appropriate for now.

Comment on lines +445 to +452
release_ids = (
GroupRelease.objects.filter(
group_id=group_id,
project_id=project_id,
)
.distinct()
.values_list("release_id", flat=True)
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High severity vulnerability may affect your project—review required:
Line 445 lists a dependency (django) with a known High severity vulnerability.

ℹ️ Why this matters

Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). SQL injection in Django's ORM column aliases: when using QuerySet.annotate(), QuerySet.alias(), QuerySet.aggregate(), or QuerySet.extra() with dictionary expansion (**kwargs), the dictionary keys are used unescaped as SQL column aliases. On MySQL and MariaDB backends, an attacker who can influence those keys (for example, by passing a crafted dict of annotations) can inject arbitrary SQL into the generated query.

References: GHSA, CVE

To resolve this comment:
Check if you are using Django with MySQL or MariaDB.

  • If you're affected, upgrade this dependency to at least version 5.2.7 at uv.lock.
  • If you're not affected, comment /fp we don't use this [condition]
💬 Ignore this finding

To ignore this, reply with:

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

You can view more details on this finding in the Semgrep AppSec Platform here.

@cmanallen cmanallen merged commit 73bbb6f into master Oct 9, 2025
64 checks passed
@cmanallen cmanallen deleted the cmanallen/releases-resolve-next-semver-release branch October 9, 2025 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Scope: Backend Automatically applied to PRs that change backend components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants